package com.bf.electroplating.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bf.electroplating.pojo.entity.Warning;
import com.bf.electroplating.pojo.entity.SewageWarningConfig;
import com.bf.electroplating.pojo.entity.InflowManagement;
import com.bf.electroplating.pojo.vo.warning.*;
import com.bf.electroplating.service.IWarningDataSyncService;
import com.bf.electroplating.service.IWarningService;
import com.bf.electroplating.service.ISewageWarningConfigService;
import com.bf.electroplating.service.IInflowManagementService;
import com.bf.electroplating.util.SignUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Comparator;
import java.util.ArrayList;
import java.math.BigDecimal;
import java.util.UUID;
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;

/**
 * 预警数据同步服务实现类
 * 
 * @author system
 * @since 2025-01-11
 */
@Slf4j
@Service
public class WarningDataSyncServiceImpl implements IWarningDataSyncService {

    @Autowired
    private IWarningService warningService;

    @Autowired
    private ISewageWarningConfigService sewageWarningConfigService;

    @Autowired
    private IInflowManagementService inflowManagementService;

    @Autowired
    private RestTemplate restTemplate;

    @Value("${company.api.baseUrl}")
    private String apiBaseUrl;

    @Value("${company.api.secret}")
    private String apiSecret;

    @Override
    public void syncElectricWarningData() {
        try {
            log.info("开始同步用电工况预警数据");
            
            // 构建请求参数
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("beginTime", getCurrentTimeMinusDays(7)); // 获取7天前的时间
            requestBody.put("endTime", getCurrentTime());
            requestBody.put("page", 1);
            requestBody.put("pageSize", 100);
            
            // 调用外部API
            String url = apiBaseUrl + "/out/alarm/electric/record/list";
            String response = callExternalApi(url, requestBody);
            
            // 解析响应数据
            @SuppressWarnings("unchecked")
            WarningApiResponseVO apiResponse = JSON.parseObject(response,
                WarningApiResponseVO.class);
            
            if (apiResponse.getSuccess() && apiResponse.getList() != null) {
                // 转换并保存数据
                List<Warning> warnings = convertElectricWarnings(apiResponse.getList());
                saveWarnings(warnings);
                log.info("用电工况预警数据同步完成，共处理{}条记录", warnings.size());
            } else {
                log.warn("用电工况预警数据同步失败，响应: {}", response);
            }
            
        } catch (Exception e) {
            log.error("同步用电工况预警数据异常", e);
        }
    }

    @Override
    public void syncRainfallWarningData() {
        try {
            log.info("开始同步雨排口预警数据");
            
            // 构建请求参数
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("beginTime", getCurrentTimeMinusDays(7)); // 获取7天前的时间
            requestBody.put("endTime", getCurrentTime());
            requestBody.put("page", 1);
            requestBody.put("pageSize", 100);
            requestBody.put("siteId", 6); // 默认站点ID，可根据需要调整
            
            // 调用外部API
            String url = apiBaseUrl + "/out/alarm/site/record/list";
            String response = callExternalApi(url, requestBody);
            
            // 解析响应数据
            @SuppressWarnings("unchecked")
            WarningApiResponseVO apiResponse = JSON.parseObject(response,
                WarningApiResponseVO.class);
            
            if (apiResponse.getSuccess() && apiResponse.getList() != null) {
                // 转换并保存数据
                List<Warning> warnings = convertRainfallWarnings(apiResponse.getList());
                saveWarnings(warnings);
                log.info("雨排口预警数据同步完成，共处理{}条记录", warnings.size());
            } else {
                log.warn("雨排口预警数据同步失败，响应: {}", response);
            }
            
        } catch (Exception e) {
            log.error("同步雨排口预警数据异常", e);
        }
    }

    @Override
    public void syncAllWarningData() {
        try {
            log.info("开始同步所有预警数据");
            syncElectricWarningData();
            syncRainfallWarningData();
            log.info("所有预警数据同步完成");
        } catch (Exception e) {
            log.error("同步所有预警数据异常", e);
        }
    }

    @Override
    public void createWarningDataHourly() {
        /**
         * 基于已有废水预警数据与废水数据生成预警
         * sewageWarningConfig表为预警配置
         * inflowManagement表为每日客户填入的实际数据
         * 基于wasterWaterType废水类型、企业id、与monitorHexavalentChromium、monitorTotalChromium、monitorTotalNickel判断是否需要进行检测
         * 基于检测结果生成warnning，warningType为3
         */
        try {
            log.info("开始生成废水预警数据");
            
            // 获取所有污水预警配置
            List<SewageWarningConfig> configs = sewageWarningConfigService.list();
            if (configs.isEmpty()) {
                log.info("未找到污水预警配置，跳过预警生成");
                return;
            }
            
            // 获取当日的进水管控数据
            LocalDate today = LocalDate.now();
            List<InflowManagement> todayInflowData = getTodayInflowData(today);
            
            // 按企业ID和废水类型分组数据
            Map<String, List<InflowManagement>> groupedData = todayInflowData.stream()
                .collect(Collectors.groupingBy(data -> data.getCompanyId() + "_" + data.getWasteWaterType()));
            
            int generatedWarnings = 0;
            
            // 遍历每个配置，检查是否需要生成预警
            for (SewageWarningConfig config : configs) {
                String key = config.getCompanyId() + "_" + config.getWasteWaterType();
                List<InflowManagement> companyData = groupedData.get(key);
                
                if (companyData != null && !companyData.isEmpty()) {
                    // 获取最新的检测数据
                    InflowManagement latestData = companyData.stream()
                        .max(Comparator.comparing(InflowManagement::getDetectionDate))
                        .orElse(companyData.get(0));
                    
                    // 检查各项指标是否超标
                    List<Warning> warnings = checkAndGenerateWarnings(config, latestData);
                    
                    if (!warnings.isEmpty()) {
                        // 保存预警记录
                        for (Warning warning : warnings) {
                            // 使用MD5签名检查是否已存在相同的预警记录
                            if (!isWarningExistsByMd5(warning.getMd5Sign())) {
                                warningService.save(warning);
                                generatedWarnings++;
                                log.info("生成废水预警记录：企业={}, 因子={}, 值={}, 阈值={}, MD5={}", 
                                    warning.getCompanyName(), warning.getWarningFactor(), 
                                    warning.getWarningValue(), warning.getWarningThreshold(), warning.getMd5Sign());
                            } else {
                                log.debug("跳过重复预警记录：企业={}, 因子={}, 检测日期={}, MD5={}", 
                                    config.getCompanyName(), warning.getWarningFactor(), latestData.getDetectionDate(), warning.getMd5Sign());
                            }
                        }
                    }
                }
            }
            
            log.info("废水预警数据生成完成，共生成{}条预警记录", generatedWarnings);
            
        } catch (Exception e) {
            log.error("生成废水预警数据异常", e);
        }
    }

    /**
     * 调用外部API
     */
    private String callExternalApi(String url, Map<String, Object> requestBody) {
        try {
            // 生成签名参数
            String signedParams = SignUtil.generateParams(requestBody);
            
            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("Content-Type", "application/json");
            
            // 创建请求实体
            HttpEntity<String> entity = new HttpEntity<>(signedParams, headers);
            
            // 发送请求
            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
            
            return response.getBody();
            
        } catch (Exception e) {
            log.error("调用外部API异常，URL: {}, 参数: {}", url, requestBody, e);
            throw new RuntimeException("调用外部API失败", e);
        }
    }

    /**
     * 转换用电工况预警数据
     */
    private List<Warning> convertElectricWarnings(List<JSONObject> electricWarnings) {
        return electricWarnings.stream().map(electricWarning -> {
            Warning warning = new Warning();
            warning.setModule("用电工况");
            warning.setWarningFactor("用电异常");
            warning.setWarningType("1");
            warning.setWarningLevel("重要");
            warning.setWarningContent(electricWarning.getString("alarmContent"));
            warning.setCompanyName(electricWarning.getString("enterprisesName"));
            warning.setWarningTime(parseDateTime(electricWarning.getString("abnormalStartTime")));
            warning.setHandleStatus(electricWarning.getString("alarmStatus"));
            warning.setCreateTime(LocalDateTime.now());
            warning.setParkId("1001");
            warning.setDelFlag("0");
            
            // 生成MD5签名用于去重
            String md5Sign = generateMd5Sign(warning);
            warning.setMd5Sign(md5Sign);
            
            return warning;
        }).collect(java.util.stream.Collectors.toList());
    }

    /**
     * 转换雨排口预警数据
     */
    private List<Warning> convertRainfallWarnings(List<JSONObject> rainfallWarnings) {
        return rainfallWarnings.stream().map(rainfallWarning -> {
            Warning warning = new Warning();
            warning.setModule("雨排口");
            warning.setWarningFactor("水质异常");
            warning.setWarningType("2");
            warning.setWarningLevel(rainfallWarning.getString("alarmGrade"));
            warning.setWarningContent(rainfallWarning.getString("alarmContent"));
            warning.setCompanyName(rainfallWarning.getString("siteName"));
            warning.setParkName(rainfallWarning.getString("regionName"));
            warning.setWarningTime(parseDateTime(rainfallWarning.getString("createTime")));
            warning.setHandleStatus(rainfallWarning.getString("alarmStatus"));
            warning.setCreateTime(LocalDateTime.now());
            warning.setDelFlag("0");
            
            // 生成MD5签名用于去重
            String md5Sign = generateMd5Sign(warning);
            warning.setMd5Sign(md5Sign);
            
            return warning;
        }).collect(java.util.stream.Collectors.toList());
    }

    /**
     * 保存预警数据
     */
    private void saveWarnings(List<Warning> warnings) {
        try {
            int savedCount = 0;
            int skippedCount = 0;
            
            for (Warning warning : warnings) {
                // 使用MD5签名检查是否已存在相同的预警记录
                if (!isWarningExistsByMd5(warning.getMd5Sign())) {
                    warningService.save(warning);
                    savedCount++;
                    log.debug("保存预警记录成功: 模块={}, 公司={}, 内容={}, MD5={}", 
                            warning.getModule(), warning.getCompanyName(), warning.getWarningContent(), warning.getMd5Sign());
                } else {
                    skippedCount++;
                    log.debug("跳过重复预警记录: 模块={}, 公司={}, 内容={}, MD5={}", 
                            warning.getModule(), warning.getCompanyName(), warning.getWarningContent(), warning.getMd5Sign());
                }
            }
            
            log.info("预警数据保存完成，新增{}条，跳过重复{}条", savedCount, skippedCount);
            
        } catch (Exception e) {
            log.error("保存预警数据异常", e);
        }
    }


    /**
     * 解析时间字符串
     */
    private LocalDateTime parseDateTime(String timeStr) {
        try {
            if (timeStr.contains(" ")) {
                return LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            } else {
                return LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            }
        } catch (Exception e) {
            log.error("解析时间字符串异常: {}", timeStr, e);
            return LocalDateTime.now();
        }
    }

    /**
     * 获取当前时间
     */
    private String getCurrentTime() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 获取N天前的时间
     */
    private String getCurrentTimeMinusDays(int days) {
        return LocalDateTime.now().minusDays(days).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 获取当日的进水管控数据
     */
    private List<InflowManagement> getTodayInflowData(LocalDate date) {
        try {
            LambdaQueryWrapper<InflowManagement> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(InflowManagement::getDetectionDate, date)
                   .eq(InflowManagement::getDelFlag, "0");
            return inflowManagementService.list(wrapper);
        } catch (Exception e) {
            log.error("获取当日进水管控数据异常", e);
            return new ArrayList<>();
        }
    }

    /**
     * 检查并生成预警
     */
    private List<Warning> checkAndGenerateWarnings(SewageWarningConfig config, InflowManagement data) {
        List<Warning> warnings = new ArrayList<>();
        
        try {
            // 检查六价铬
            if ("1".equals(config.getMonitorHexavalentChromium()) && 
                config.getHexavalentChromiumThreshold() != null && 
                data.getHexavalentChromiumValue() != null) {
                
                if (data.getHexavalentChromiumValue().compareTo(config.getHexavalentChromiumThreshold()) > 0) {
                    Warning warning = createWarning(config, data, "六价铬", 
                        data.getHexavalentChromiumValue(), config.getHexavalentChromiumThreshold());
                    warnings.add(warning);
                }
            }
            
            // 检查总铬
            if ("1".equals(config.getMonitorTotalChromium()) && 
                config.getTotalChromiumThreshold() != null && 
                data.getTotalChromiumValue() != null) {
                
                if (data.getTotalChromiumValue().compareTo(config.getTotalChromiumThreshold()) > 0) {
                    Warning warning = createWarning(config, data, "总铬", 
                        data.getTotalChromiumValue(), config.getTotalChromiumThreshold());
                    warnings.add(warning);
                }
            }
            
            // 检查总镍
            if ("1".equals(config.getMonitorTotalNickel()) && 
                config.getTotalNickelThreshold() != null && 
                data.getTotalNickelValue() != null) {
                
                if (data.getTotalNickelValue().compareTo(config.getTotalNickelThreshold()) > 0) {
                    Warning warning = createWarning(config, data, "总镍", 
                        data.getTotalNickelValue(), config.getTotalNickelThreshold());
                    warnings.add(warning);
                }
            }
            
        } catch (Exception e) {
            log.error("检查预警条件异常，企业ID: {}, 废水类型: {}", 
                config.getCompanyId(), config.getWasteWaterType(), e);
        }
        
        return warnings;
    }


    /**
     * 创建预警记录
     */
    private Warning createWarning(SewageWarningConfig config, InflowManagement data, 
                                 String factorName, BigDecimal actualValue, BigDecimal threshold) {
        Warning warning = new Warning();
        warning.setId(UUID.randomUUID().toString().replace("-", ""));
        warning.setModule("废水预警");
        warning.setWarningFactor(factorName);
        warning.setWarningType("3"); // 废水预警类型
        warning.setWarningLevel("重要");
        warning.setWarningContent(String.format("企业%s的%s废水%s超标，检测值：%s，阈值：%s", 
            config.getCompanyName(), config.getWasteWaterType(), factorName, actualValue, threshold));
        warning.setCompanyName(config.getCompanyName());
        warning.setCompanyId(config.getCompanyId());
        warning.setParkId(config.getParkId());
        warning.setWarningValue(actualValue);
        warning.setWarningThreshold(threshold);
        warning.setWarningTime(LocalDateTime.now());
        warning.setHandleStatus("0"); // 未处理
        warning.setCreateTime(LocalDateTime.now());
        warning.setDelFlag("0");
        
        // 生成MD5签名用于去重
        String md5Sign = generateMd5Sign(warning);
        warning.setMd5Sign(md5Sign);
        
        return warning;
    }

    /**
     * 生成预警记录的MD5签名
     * 基于关键字段生成唯一标识，用于去重判断
     */
    private String generateMd5Sign(Warning warning) {
        try {
            // 构建用于生成MD5的字符串，包含关键字段
            StringBuilder signBuilder = new StringBuilder();
            signBuilder.append(warning.getModule()).append("|");
            signBuilder.append(warning.getWarningFactor()).append("|");
            signBuilder.append(warning.getWarningType()).append("|");
            signBuilder.append(warning.getCompanyName()).append("|");
            signBuilder.append(warning.getWarningContent()).append("|");
            signBuilder.append(warning.getWarningTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))).append("|");
            signBuilder.append(warning.getWarningLevel()).append("|");
            
            // 如果有预警值，也加入签名
            if (warning.getWarningValue() != null) {
                signBuilder.append(warning.getWarningValue().toString()).append("|");
            }
            if (warning.getWarningThreshold() != null) {
                signBuilder.append(warning.getWarningThreshold().toString()).append("|");
            }
            
            String signString = signBuilder.toString();
            
            // 生成MD5
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hashBytes = md.digest(signString.getBytes(StandardCharsets.UTF_8));
            
            // 转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hashBytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            
            return hexString.toString();
            
        } catch (Exception e) {
            log.error("生成MD5签名异常", e);
            // 异常时返回基于时间戳的备用签名
            return "fallback_" + System.currentTimeMillis();
        }
    }

    /**
     * 基于MD5签名检查预警记录是否已存在
     */
    private boolean isWarningExistsByMd5(String md5Sign) {
        try {
            return warningService.count(
                new LambdaQueryWrapper<Warning>()
                    .eq(Warning::getMd5Sign, md5Sign)
                    .eq(Warning::getDelFlag, "0") // 只检查未删除的记录
            ) > 0;
        } catch (Exception e) {
            log.error("检查预警记录MD5签名是否存在异常，MD5: {}", md5Sign, e);
            return false; // 异常时返回false，允许保存
        }
    }
}
